import React, { useEffect, useState } from 'react';
import { createStore, Action } from 'redux';
import { useSelector, Provider } from 'react-redux';

interface IState {
  a: number;
  b: number;
}
const initState: IState = {
  a: 1,
  b: 2,
}
const reducer = (state: IState = initState, action: Action): IState => {
  const fnMap = {
    inca: (state: IState): IState => ({ ...state, a: state.a + 1 }),
    incb: (state: IState): IState => ({ ...state, b: state.b + 1 }),
  };
  const fn = fnMap[action.type];
  if (fn) {
    return fn(state);
  } else {
    return state;
  }
}
const store = createStore(reducer);

/**
 * 确保当 dispatch 发生，使用本hook的组件能够刷新
 */
function useRefreshForStoreChange() {
  const [state, setState] = useState(() => store.getState());
  useEffect(() => {
    // store 变化了，更新 state 变量，从而刷新组件，
    return store.subscribe(() => {
      setState(() => store.getState());
    });
  }, []);
  return state;
}

/**
 * 自己实现 react-redux useSelector
 * @param selector
 */
function useSelector2(selector: any) {
  // const store = useContext(Provider);
  const [slice, setSlice] = useState(() => selector(store.getState()));
  useEffect(() => {
    // store 变化了，刷新组件
    store.subscribe(() => {
      setSlice(() => selector(store.getState()));
    });
  }, []);
  return slice;
}

/**
 * 直接订阅整个 store 刷新
 */
function ReduxBasic() {
  const state = store.getState();
  useRefreshForStoreChange();
  return (
    <div>
      <button onClick={() => store.dispatch({ type: 'inca' })}>inca</button>
      <button onClick={() => store.dispatch({ type: 'incb' })}>incb</button>
      <div>{state.a} | {state.b}</div>
    </div >
  )
}

/**
 * 使用自定义的 useSelector2 订阅 store slice
 */
function TryUseSelector2() {
  const a = useSelector((v: IState) => v.a); // 从 Provider.store 取数据
  const b = useSelector2((v: IState) => v.b);
  return (
    <div>
      <button onClick={() => store.dispatch({ type: 'inca' })}>inca</button>
      <button onClick={() => store.dispatch({ type: 'incb' })}>incb</button>
      <div> {a} | {b}</div>
    </div >
  )
}

/**
 * 提供 store provide 供内部使用
 */
export default function ReduxBasicProvider() {
  const [count, setCount] = useState(0);
  return (
    <Provider store={store}>
      {count <= 3 && <ReduxBasic />}
      <TryUseSelector2 />
      <button onClick={() => setCount(v => v + 1)}>add one {count}</button>
    </Provider>
  );
}
